package com.linxiao.call.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.thread.ThreadUtil;
import com.linxiao.call.domain.CrmWebcallFile;
import com.linxiao.call.domain.CrmWebcallFileTel;
import com.linxiao.call.mapper.CrmWebcallFileTelMapper;
import com.linxiao.call.service.ICrmWebcallFileService;
import com.linxiao.call.service.ICrmWebcallFileTelService;
import com.ruoyi.common.constant.CrmFileTaskConstants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.EncryptContent;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.Threads;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import static java.util.stream.Collectors.*;

/**
 * 语音通知批次号码Service业务层处理
 *
 * @author qiqi
 * @date 2022-06-28
 */
@Service
public class CrmWebcallFileTelServiceImpl implements ICrmWebcallFileTelService {
    @Resource
    private CrmWebcallFileTelMapper crmWebcallFileTelMapper;

    @Resource
    private ICrmWebcallFileTelService crmWebcallFileTelService;

    @Resource
    private ICrmWebcallFileService crmWebcallFileService;


    public Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 查询语音通知批次号码
     *
     * @param id 语音通知批次号码主键
     * @return 语音通知批次号码
     */
    @Override
    public CrmWebcallFileTel selectCrmWebcallFileTelById(Long id) {
        return crmWebcallFileTelMapper.selectCrmWebcallFileTelById(id);
    }

    /**
     * 查询语音通知批次号码列表
     *
     * @param crmWebcallFileTel 语音通知批次号码
     * @return 语音通知批次号码
     */
    @Override
    public List<CrmWebcallFileTel> selectCrmWebcallFileTelList(CrmWebcallFileTel crmWebcallFileTel) {

        return crmWebcallFileTelMapper.selectCrmWebcallFileTelList(crmWebcallFileTel);
    }

    /**
     * 新增语音通知批次号码
     *
     * @param crmWebcallFileTel 语音通知批次号码
     * @return 结果
     */
    @Override
    public int insertCrmWebcallFileTel(CrmWebcallFileTel crmWebcallFileTel) {
        crmWebcallFileTel.setCreateTime(DateUtils.getNowDate());
        CrmWebcallFile webcallFile = crmWebcallFileService.selectCrmWebcallFileById(crmWebcallFileTel.getFileId());
        crmWebcallFileTel.setFileName(webcallFile.getName());
        // 脱敏手机号
        crmWebcallFileTel.setMobileHidden(EncryptContent.replaceAction(crmWebcallFileTel.getTel()));

        return crmWebcallFileTelMapper.insertCrmWebcallFileTel(crmWebcallFileTel);
    }

    /**
     * 修改语音通知批次号码
     *
     * @param crmWebcallFileTel 语音通知批次号码
     * @return 结果
     */
    @Override
    public int updateCrmWebcallFileTel(CrmWebcallFileTel crmWebcallFileTel) {
        crmWebcallFileTel.setUpdateTime(DateUtils.getNowDate());
        if(StringUtils.isNotEmpty(crmWebcallFileTel.getTel())){
            // 脱敏手机号
            crmWebcallFileTel.setMobileHidden(EncryptContent.replaceAction(crmWebcallFileTel.getTel()));

        }
        return crmWebcallFileTelMapper.updateCrmWebcallFileTel(crmWebcallFileTel);
    }

    /**
     * 批量删除语音通知批次号码
     *
     * @param ids 需要删除的语音通知批次号码主键
     * @return 结果
     */
    @Override
    public AjaxResult deleteCrmWebcallFileTelByIds(Long[] ids) {

        int count = crmWebcallFileTelMapper.deleteCrmWebcallFileTelByIds(ids);
        if (count > 0) {
            return new AjaxResult(HttpStatus.SUCCESS, "删除成功");
        }
        return new AjaxResult(HttpStatus.ERROR, "删除失败");
    }

    /**
     * 删除语音通知批次号码信息
     *
     * @param id 语音通知批次号码主键
     * @return 结果
     */
    @Override
    public int deleteCrmWebcallFileTelById(Long id) {
        return crmWebcallFileTelMapper.deleteCrmWebcallFileTelById(id);
    }

    /**
     * 统计批次中的号码个数
     *
     * @param id
     * @return
     */
    @Override
    public int countById(Long id) {
        return crmWebcallFileTelMapper.countById(id);
    }

    /**
     * 批量导出
     *
     * @param fileTelList
     * @return
     */
    @Override
    @SuppressWarnings("all")
    public AjaxResult importFileTel(List<CrmWebcallFileTel> fileTelList, Long fileId) {
        // 1、判断批次是否存在
        CrmWebcallFile crmWebcallFile = crmWebcallFileService.selectCrmWebcallFileById(fileId);
        if (crmWebcallFile == null) {
            return AjaxResult.error(HttpStatus.ERROR, "根据批次ID不能获得对应的批次信息！！！");
        }

        // 2、批次在运行不能导入
        if (CrmFileTaskConstants.RUNING_VALUE.equals(crmWebcallFile.getStatus())) {
            return AjaxResult.error(HttpStatus.ERROR, "当前批次正在运行中不能导入！！！");
        }

        // 3、号码导入最大条数限制
        if (fileTelList.size() > CrmFileTaskConstants.TASK_TEL_MAX_IMPORT_COUNT) {
            return AjaxResult.error(HttpStatus.ERROR, "号码超出最大导入条数限制！！！");
        }

        try {
            ThreadUtil.execAsync(() -> {
                int importCount = 0;
                int repeatCount = 0;
                // 存储最终插入的数据
                List<CrmWebcallFileTel> insertWebcallFileTel = new ArrayList<>();
                // 存储重复的数据
                List<CrmWebcallFileTel> distinctWebcallFileTel = new ArrayList<>();


                // 将 导入的号码去重 根据tel 去重
                List<CrmWebcallFileTel> distinctFileTelList = fileTelList.stream().collect(
                        collectingAndThen(
                                toCollection(() -> new TreeSet<>(Comparator.comparing(CrmWebcallFileTel::getTel))), ArrayList::new));

                // 将批次ID和批次名称设置给每个List对象
                distinctFileTelList.stream().forEach(item -> {
                    item.setFileId(fileId);
                    item.setFileName(crmWebcallFile.getName());
                });

                // 判断是否存在已有批次的号码数据
                CrmWebcallFileTel webcallFileTelParam = new CrmWebcallFileTel();
                webcallFileTelParam.setFileId(fileId);
                List<CrmWebcallFileTel> crmWebcallFileTels = crmWebcallFileTelMapper.selectCrmWebcallFileTelList(webcallFileTelParam);

                if (StringUtils.isNull(crmWebcallFileTels) || crmWebcallFileTels.size() == 0) {
                    // 计算 导入号码的重复数据
                    repeatCount = fileTelList.size() - distinctFileTelList.size();
                    insertWebcallFileTel = distinctFileTelList;
                    importCount = insertWebcallFileTel.size();
                } else {
                    // 去重后的数据 和已存在的批次数据 再次判断是否重复（取差集）
                    insertWebcallFileTel = distinctFileTelList.stream().filter(fileTel ->
                            !crmWebcallFileTels.stream().map(CrmWebcallFileTel::getTel).collect(Collectors.toList()).contains(fileTel.getTel()))
                            .collect(Collectors.toList());
                    // 根据tel 字段获得两个集合中tel相同的数据
                    distinctWebcallFileTel= distinctFileTelList.stream().filter(a->
                            crmWebcallFileTels.stream().map(b-> b.getTel()).collect(Collectors.toList()).contains(a.getTel())
                    ).collect(Collectors.toList());
                    repeatCount = distinctWebcallFileTel.size();
                    importCount = insertWebcallFileTel.size();
                }

                // 添加批次号码数
                List<CrmWebcallFileTel> insertTaskTelList = new ArrayList<>();

                Long startTimeMillis = System.currentTimeMillis();
                long tick = 0;
                try {
                    for (int i = 0; i < insertWebcallFileTel.size(); i++) {

                        insertTaskTelList.add(insertWebcallFileTel.get(i));

                        if (i == insertWebcallFileTel.size() - 1 || ((i != 0) && (i % 100 == 0))) {

                            if (insertWebcallFileTel.size() > 0) {
                                insertTaskTelList.stream().forEach(item ->{
                                    // 脱敏手机号
                                    item.setMobileHidden(EncryptContent.replaceAction(item.getTel()));
                                });
                                crmWebcallFileTelMapper.batchInsertFileTel(insertTaskTelList);
                                insertTaskTelList = new ArrayList<>();
                            }
                        }
                    }
                    tick = System.currentTimeMillis() - startTimeMillis;



                    // 更新号码数 和重复数
                    CrmWebcallFile crmWebcallFile1 = new CrmWebcallFile();
                    crmWebcallFile1.setImportCount(Long.valueOf(importCount));
                    crmWebcallFile1.setRepeatCount(Long.valueOf(repeatCount));
                    crmWebcallFile1.setStatus(CrmFileTaskConstants.IMPORT_VALUE);
                    crmWebcallFile1.setId(fileId);
                    int count = crmWebcallFileService.updateCrmWebcallFile(crmWebcallFile1);
                    if (count != 1) {
                        logger.info("批次信息更新失败 taskId={}", fileId);
                    }
                } catch (Exception e) {
                    logger.error("号码导入失败", e);
                }finally {
                    logger.info("importFileTel fileId ={},号码导入总耗时 time = {}", fileId, tick);
                }

            });
        } catch (Exception e) {
            logger.error("executorService.execute error", e);
            return new AjaxResult(HttpStatus.ERROR, "导入失败, 请稍后重试");
        }
        Map<String, Long> resultMap = new HashMap<>();
        resultMap.put("fileId", fileId);
        return AjaxResult.success("导入成功", resultMap);

    }

    /**
     * 批量更新号码状态
     * @param fileTelList
     * @return
     */
    @Override
    public int batchUpdateFileTel(List<CrmWebcallFileTel> fileTelList) {
        return crmWebcallFileTelMapper.batchUpdateFileTel(fileTelList);
    }

    @Override
    public int updateCrmWebcallFileTelByFileId(CrmWebcallFileTel crmWebcallFileTel) {
        return crmWebcallFileTelMapper.updateCrmWebcallFileTelByFileId(crmWebcallFileTel);
    }
}
